#pragma once
#include <cstdint>

#define OPENGLAPI inline

namespace opengl {

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
using f32 = float;
using f64 = double;
using voidptr = void *;

enum data_type : u32 {
    type_i8 = 0x1400,  // GL_BYTE
    type_i16 = 0x1403, // GL_SHORT
    type_i32 = 0x1404, // GL_INT
    type_i64 = 0x140C, // GL_LONG
    type_u8 = 0x1401,  // GL_UNSIGNED_BYTE
    type_u16 = 0x1402, // GL_UNSIGNED_SHORT
    type_u32 = 0x1405, // GL_UNSIGNED_INT
    type_u64 = 0x140B, // GL_UNSIGNED_LONG
    type_f32 = 0x1406, // GL_FLOAT
    type_f64 = 0x140A, // GL_DOUBLE
};

enum data_format : u32 {
    format_r8 = 0x8229,      // GL_R8
    format_rg8 = 0x822B,     // GL_RG8
    format_rgb8 = 0x8051,    // GL_RGB8
    format_rgba8 = 0x8058,   // GL_RGBA8
    format_r32f = 0x822E,    // GL_R32F
    format_rg32f = 0x8230,   // GL_RG32F
    format_rgb32f = 0x8815,  // GL_RGB32F
    format_rgba32f = 0x8814, // GL_RGBA32F
};

enum draw_mode : u32 {
    mode_triangles = 0x0004,      // GL_TRIANGLES
    mode_triangle_strip = 0x0005, // GL_TRIANGLE_STRIP
    mode_triangle_fan = 0x0006,   // GL_TRIANGLE_FAN
    mode_lines = 0x0001,          // GL_LINES
    mode_line_strip = 0x0003,     // GL_LINE_STRIP
    mode_line_loop = 0x0002,      // GL_LINE_LOOP
    mode_points = 0x0000,         // GL_POINTS
};

enum culling_mode : u32 {
    mode_back = 0x0405,          // GL_BACK
    mode_front = 0x0404,         // GL_FRONT
    mode_front_and_back = 0x0408 // GL_FRONT_AND_BACK
};

enum compare_func : u32 {
    cmp_never = 0x0200,    // GL_NEVER
    cmp_less = 0x0201,     // GL_LESS
    cmp_equal = 0x0202,    // GL_EQUAL
    cmp_lequal = 0x0203,   // GL_LEQUAL
    cmp_greater = 0x0204,  // GL_GREATER
    cmp_notequal = 0x0205, // GL_NOTEQUAL
    cmp_gequal = 0x0206,   // GL_GEQUAL
    cmp_always = 0x0207    // GL_ALWAYS
};

enum opengl_functions : u32 {
    depth_test = 0x0B71,   // GL_DEPTH_TEST
    blend = 0x0BE2,        // GL_BLEND
    cull_face = 0x0B44,    // GL_CULL_FACE
    scissor_test = 0x0C11, // GL_SCISSOR_TEST
    stencil_test = 0x0B90  // GL_STENCIL_TEST
};

// Avoid macro substitution
constexpr const u32 OPENGL_NO_ERROR = 0;
constexpr const u32 OPENGL_COLOR_BUFFER_BIT = 0x00004000;
constexpr const u32 OPENGL_TEXTURE_2D = 0x0DE1;
constexpr const u32 OPENGL_DEPTH_BUFFER_BIT = 0x00000100;
constexpr const u32 OPENGL_STENCIL_BUFFER_BIT = 0x00000400;
constexpr const u32 OPENGL_ARRAY_BUFFER = 0x8892;
constexpr const u32 OPENGL_ELEMENT_ARRAY_BUFFER = 0x8893;
constexpr const u32 OPENGL_STATIC_DRAW = 0x88E4;
constexpr const u32 OPENGL_DYNAMIC_DRAW = 0x88E8;
constexpr const u32 OPENGL_STREAM_DRAW = 0x88E0;
constexpr const u32 OPENGL_FLOAT = 0x1406;
constexpr const u32 OPENGL_UNSIGNED_BYTE = 0x1401;
constexpr const u32 OPENGL_UNSIGNED_INT = 0x1405;
constexpr const u32 OPENGL_TEXTURE_MIN_FILTER = 0x2801;
constexpr const u32 OPENGL_TEXTURE_MAG_FILTER = 0x2800;
constexpr const u32 OPENGL_TEXTURE_WRAP_S = 0x2802;
constexpr const u32 OPENGL_TEXTURE_WRAP_T = 0x2803;
constexpr const u32 OPENGL_TEXTURE_2D_ARRAY = 0x8C1A;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP = 0x8513;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519;
constexpr const u32 OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A;
constexpr const u32 OPENGL_CLAMP_TO_EDGE = 0x812F;
constexpr const u32 OPENGL_REPEAT = 0x2901;
constexpr const u32 OPENGL_LINEAR = 0x2601;
constexpr const u32 OPENGL_NEAREST = 0x2600;
constexpr const u32 OPENGL_RGBA = 0x1908;
constexpr const u32 OPENGL_RGB = 0x1907;
constexpr const u32 OPENGL_RED = 0x1903;
constexpr const u32 OPENGL_RG = 0x8227;
constexpr const u32 OPENGL_VERTEX_SHADER = 0x8B31;
constexpr const u32 OPENGL_FRAGMENT_SHADER = 0x8B30;
constexpr const u32 OPENGL_COMPILE_STATUS = 0x8B81;
constexpr const u32 OPENGL_LINK_STATUS = 0x8B82;
constexpr const u32 OPENGL_INFO_LOG_LENGTH = 0x8B84;
constexpr const u32 OPENGL_DYNAMIC_STORAGE_BIT = 0x0100;
constexpr const u32 OPENGL_MAP_READ_BIT = 0x0001;
constexpr const u32 OPENGL_MAP_WRITE_BIT = 0x0002;
constexpr const u32 OPENGL_MAP_PERSISTENT_BIT = 0x0040;
constexpr const u32 OPENGL_MAP_COHERENT_BIT = 0x0080;
constexpr const u32 OPENGL_BUFFER_SIZE = 0x8764;
constexpr const u32 OPENGL_BUFFER_USAGE = 0x8765;
constexpr const u32 OPENGL_BUFFER_FLAGS = 0x911F;

} // namespace opengl